package cli.menu;


import shared.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;
import java.util.SortedSet;


public class TrackExpenses extends Function{
	
	private static String[] select = {
		"-= Main menu > Track Expenses =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"",
		"Please selet a time frame",
		"1. Today",
		"2. This Month",
		"3. This Year",
		"",
		"Option: "
	};
	
	private static State back = State.MAINMENU;
	private static State current = State.TRACKEXPENSES;
	
	public static State runMenu(){
		
		cli.print(select);
		
		String input = cli.nextLine();
		
		return processInput(input);
		
	}
	
	private static State processInput(String input){
		
		State nextState = current;
		if(input.length() != 1){
			return current;
		}
		else{
		
			char charInput = input.charAt(0);
			switch (charInput) {
			case '1':
				nextState = printTrackExpense("day",true);
				break;
			case '2':
				nextState = printTrackExpense("month",true);
				break;
			case '3':
				nextState = printTrackExpense("year",true);
				break;
			case 'u':
			case 'U':
				tools.undo();
				break;
			case 'r':
			case 'R':
				tools.redo();
				break;
			case 'b':
			case 'B':
			case 'H':
			case 'h':
				nextState = back;
				break;
			default:
				cli.print(INVALIDINPUT);
			}			
		}	
		return nextState;
	}
	
	public static State printTrackExpense(String option, boolean printHeader) {

		// ============print header ====================================
		Date currentDate = new Date();
		String date = tools.formatDate(currentDate);


		int[] today = new int[3];
		today = tools.initDate();
		int day = today[0];
		int month = today[1];
		int year = today[2];
		SortedSet<Record> record = null;

		if (option.equalsIgnoreCase("day")) {
			record = cli.getApi().getDateRange(day, month, year, day + 1, month, year);
		} else if (option.equalsIgnoreCase("month")) {
			record = cli.getApi().getDateRange(1, month, year, day + 1, month, year);
		} else if (option.equalsIgnoreCase("year")) {
			record = cli.getApi().getDateRange(1, 1, year, day + 1, month, year);
		} else {
			cli.print(ERROR);
		}

		Object[] recordArr = record.toArray();

		// calculate total spent & total owed
		int spent = 0;
		int owed = 0;

		for (Object r : recordArr) {
			if (r.getClass() == Expense.class) {
				spent += ((Record) r).getAmt();
			}
			if (r.getClass() == Loan.class) {
				owed += ((Loan) r).getOutstanding();
			}
		}

		double totalExpense = (double) spent / 100.00;
		double// totalOutstanding = (double) owed / 100.00;
		totalOutstanding = cli.getApi().getOutstanding() / 100.00;

	if(printHeader){
		cli.println("-= Main menu > Track Expenses > This Year =-");
		cli.println( "[b]: back [u]: undo [r]: redo [h]: home menu");
	}
		cli.println("");
		if (option.equalsIgnoreCase("day")) {
			cli.println("For the Day " + date);
		} else if (option.equalsIgnoreCase("month")) {
			cli.println("For the Month " + month + "." + year);
		} else if (option.equalsIgnoreCase("year")) {
			cli.println("For the Year " + year);
		} else {
			cli.println("track expense request option is not available");
			return current;
		}
	
		cli.printf("Amount you spent:     $%.2f\n", totalExpense);
		//cli.printf("Amount you owed:  $%.2f\n", totalOutstanding);
		cli.printf("Current amount owed:  $%.2f\n", totalOutstanding);
		cli.println("\nSpending by Categories\n");

		// ====================end of print header ==========================

		// ====================print bar chart ==============================
		ArrayList<Category> cat = cli.getApi().getCategoryList();
		// create array to store category and total expense in that category
		CatSpend catEx[] = new CatSpend[cat.size()];
		// for convenience, create hash table to map category to index of
		// catEx[]
		Hashtable<Category, Integer> ht = new Hashtable<Category, Integer>();
		for (int i = 0; i < cat.size(); i++) {
			catEx[i] = new CatSpend(cat.get(i), 0); // initialize CatSpend
			// objects
			ht.put(cat.get(i), i);
		}

		// sum expenses by categories
		Expense e;
		CatSpend cs;
		for (Record r : record) {
			if (r.getClass() == Expense.class) {
				e = (Expense) r;
				cs = catEx[ht.get(e.getCat())];
				cs.setExpense(cs.getExpense() + e.getAmt());
			}
		}

		// Sort catEx[] in descending expense
		CatSpendComparator exComp = new CatSpendComparator();
		Arrays.sort(catEx, exComp);

		int charToPrint;
		String catName;
		double spending;

		// set bar chart parameters
		int WIDTH = 50; // max bar length
		double factor = (double) WIDTH / catEx[cat.size() - 1].getExpense(); // ratio
		int NAME_LENGTH = 15; // category name field length

		// constant string to print
		String emptyName = tools.printLine(" ", NAME_LENGTH);

		// print bar chart
		cli.print(emptyName);
		cli.println("|");
		for (int i = 0; i < catEx.length; i++) {
			catName = tools.formatString(catEx[i].getCat().getName(), NAME_LENGTH);
			spending = (double) catEx[i].getExpense() / 100.00;
			charToPrint = (int) (catEx[i].getExpense() * factor);
			cli.print(catName + "|");

			cli.print(tools.printLine("=", charToPrint));

			cli.printf(" $%.2f\n", spending);

			cli.print(emptyName);

			cli.println("|");
		}
		// ===========end of print bar chart
		// ====================================
		
		if(!printHeader){
			return current;
		}
		
		String input = cli.nextLine();
		return leaveTrackReport(input);
	}
	// **END**



//This method is to take in input after the trackExpense report has been printed
//to determine the next screen
public static State leaveTrackReport(String input){
	
	State nextState = current;

	if(input == null || input.length() != 1)
		return current;
	char charInput = input.charAt(0);
			
	switch (charInput) {
	case 'b':
	case 'B':
		nextState = back;
		break;
	case 'u':
	case 'U':
		tools.undo();
		break;
	case 'r':
	case 'R':
		tools.redo();
		break;
	case 'h':
	case 'H':
		nextState = State.MAINMENU;
		break;
		//default stays at current
	default:
		break;
	}

	return nextState;

}
	
	

}